/* Rubik's Cube
 */

import java.util.ArrayList;
import java.util.Hashtable;

// Libraries

/**
 * Holds cube state and methods for manipulations
 * 
 * @author Yung-Hsiang Lu adapted to Java by Jacob Wyant
 */

@SuppressWarnings("serial")
// Doesn't need to be serialized
public class RubikCube {

	private static final int NUMFACE = 6;
	private static final int CUBESIZE = 3;
	private static final char FACECOLOR[] = { 'Y', 'R', 'G', 'O', 'B', 'W' };
	private static Hashtable<String, Integer> COLORMAP = new Hashtable<String, Integer>() {
		{
			put("Y", new Integer(0));
			put("R", new Integer(1));
			put("G", new Integer(2));
			put("O", new Integer(3));
			put("B", new Integer(4));
			put("W", new Integer(5));
		}
	};
	private int cState[][][];
	private ArrayList<String> rotate = new ArrayList<String>();

	public RubikCube() {

		// InitColorMap();
		cState = new int[NUMFACE][CUBESIZE][CUBESIZE];
		/*
		 * for (int face = 0; face < NUMFACE; face ++) { cState[face] = new int
		 * * [CUBESIZE]; for (int row = 0; row < CUBESIZE; row ++) {
		 * cState[face][row] = new int [CUBESIZE]; } }
		 */
		reset();
	}

	public void reset() {
		for (int face = 0; face < NUMFACE; face++) {
			for (int row = 0; row < CUBESIZE; row++) {
				for (int col = 0; col < CUBESIZE; col++) {
					cState[face][row][col] = face;
				}
			}
		}
		rotate.clear();
	}

	public void command(String t) {
		if (t.contentEquals("RESET")) {
			reset();
			return;
		}
		if (t.contentEquals("OUTPUT")) {
			print();
			return;
		}
		if (t.contentEquals("F")) {
			Fturn();
			return;
		}
		if (t.contentEquals("F'")) {
			Fpturn();
			return;
		}
		if (t.contentEquals("R")) {
			Rturn();
			return;
		}
		if (t.contentEquals("R'")) {
			Rpturn();
			return;
		}
		if (t.contentEquals("U")) {
			Uturn();
			return;
		}
		if (t.contentEquals("U'")) {
			Upturn();
			return;
		}
		if (t.contentEquals("B")) {
			Bturn();
			return;
		}
		if (t.contentEquals("B'")) {
			Bpturn();
			return;
		}
		if (t.contentEquals("L")) {
			Lturn();
			return;
		}
		if (t.contentEquals("L'")) {
			Lpturn();
			return;
		}
		if (t.contentEquals("D")) {
			Dturn();
			return;
		}
		if (t.contentEquals("D'")) {
			Dpturn();
			return;
		}
		if (t.contentEquals("X")) {
			rotate.add(0, "X");
			Xrotate();
			return;
		}
		if (t.contentEquals("X'")) {
			rotate.add(0, "X'");
			Xprotate();
			return;
		}
		if (t.contentEquals("Y")) {
			rotate.add(0, "Y");
			Yrotate();
			return;
		}
		if (t.contentEquals("Y'")) {
			rotate.add(0, "Y'");
			Yprotate();
			return;
		}
		if (t.contentEquals("Z")) {
			rotate.add(0, "Z");
			Zrotate();
			return;
		}
		if (t.contentEquals("Z'")) {
			rotate.add(0, "Z'");
			Zprotate();
			return;
		}
		if (t.contentEquals("")) {
			return;
		}
		if (t.contentEquals("\n")) {
			return;
		}
		if (IsCubeState(t)) {
			ReadState(t);
			return;
		}
		System.out.println("\nUnknown Command - (" + t + ")\n");
	}

	public void ReadState(String t) {
		int c = 0;
		for (int face = 0; face < NUMFACE; face++) {
			for (int row = 0; row < CUBESIZE; row++) {
				for (int col = 0; col < CUBESIZE; col++) {
					cState[face][row][col] = COLORMAP.get(Character.toString(t
							.charAt(c++)));
				}
			}
		}
	}

	private void Clockwise(int f) {
		// turn a face clockwise 90 degrees, it is actually matrix transpose
		int c00 = cState[f][0][0];
		int c01 = cState[f][0][1];
		int c02 = cState[f][0][2];
		int c10 = cState[f][1][0];
		// [*][1][1] (center in each face) never changes
		int c12 = cState[f][1][2];
		int c20 = cState[f][2][0];
		int c21 = cState[f][2][1];
		int c22 = cState[f][2][2];

		cState[f][0][0] = c20;
		cState[f][0][1] = c10;
		cState[f][0][2] = c00;

		cState[f][1][0] = c21;
		cState[f][1][2] = c01;

		cState[f][2][0] = c22;
		cState[f][2][1] = c12;
		cState[f][2][2] = c02;
	}

	private void CounterClockwise(int f) {
		// turn a face counterclockwise
		int c00 = cState[f][0][0];
		int c01 = cState[f][0][1];
		int c02 = cState[f][0][2];
		int c10 = cState[f][1][0];
		int c12 = cState[f][1][2];
		int c20 = cState[f][2][0];
		int c21 = cState[f][2][1];
		int c22 = cState[f][2][2];

		cState[f][0][0] = c02;
		cState[f][0][1] = c12;
		cState[f][0][2] = c22;

		cState[f][1][0] = c01;
		cState[f][1][2] = c21;

		cState[f][2][0] = c00;
		cState[f][2][1] = c10;
		cState[f][2][2] = c20;
	}

	private void Fturn() {
		// clockwise turn the front face
		// affected faces 0, 2, 5, 4
		// new <- original
		// 4 <- 5
		// 5 <- 2
		// 2 <- 0
		// 0 <- 4
		// store the values of face 4 before they are overwritten
		// "c" means color
		int c402 = cState[4][0][2];
		int c412 = cState[4][1][2];
		int c422 = cState[4][2][2];
		// new 4 = original 5
		cState[4][0][2] = cState[5][2][0];
		cState[4][1][2] = cState[5][1][0];
		cState[4][2][2] = cState[5][0][0];
		// new 5 = original 2
		cState[5][0][0] = cState[2][0][0];
		cState[5][1][0] = cState[2][1][0];
		cState[5][2][0] = cState[2][2][0];
		// new 2 = original 0
		cState[2][0][0] = cState[0][0][0];
		cState[2][1][0] = cState[0][1][0];
		cState[2][2][0] = cState[0][2][0];
		// new 0 = original 4
		cState[0][0][0] = c422;
		cState[0][1][0] = c412;
		cState[0][2][0] = c402;

		// even though face 1's colors do not change, the orientation turns
		// clockwise by 90 degrees
		Clockwise(1);
	}

	private void Fpturn() {
		// F': counterclockwise turn the front face
		// 4 <- 0
		// 0 <- 2
		// 2 <- 5
		// 5 <- 4
		int c402 = cState[4][0][2];
		int c412 = cState[4][1][2];
		int c422 = cState[4][2][2];
		// new 4 = original 0
		cState[4][0][2] = cState[0][2][0];
		cState[4][1][2] = cState[0][1][0];
		cState[4][2][2] = cState[0][0][0];
		// new 0 = original 2
		cState[0][0][0] = cState[2][0][0];
		cState[0][1][0] = cState[2][1][0];
		cState[0][2][0] = cState[2][2][0];
		// new 2 = original 5
		cState[2][0][0] = cState[5][0][0];
		cState[2][1][0] = cState[5][1][0];
		cState[2][2][0] = cState[5][2][0];
		// new 5 = original 4
		cState[5][0][0] = c422;
		cState[5][1][0] = c412;
		cState[5][2][0] = c402;

		CounterClockwise(1);
	}

	private void Rturn() {
		// clockwise turn the right face
		// 0 <- 1
		// 1 <- 5
		// 5 <- 3
		// 3 <- 0
		int c020 = cState[0][2][0];
		int c021 = cState[0][2][1];
		int c022 = cState[0][2][2];

		cState[0][2][0] = cState[1][2][2];
		cState[0][2][1] = cState[1][1][2];
		cState[0][2][2] = cState[1][0][2];

		cState[1][0][2] = cState[5][0][0];
		cState[1][1][2] = cState[5][0][1];
		cState[1][2][2] = cState[5][0][2];

		cState[5][0][0] = cState[3][2][0];
		cState[5][0][1] = cState[3][1][0];
		cState[5][0][2] = cState[3][0][0];

		cState[3][2][0] = c022;
		cState[3][1][0] = c021;
		cState[3][0][0] = c020;

		Clockwise(2);
	}

	private void Rpturn() {
		// R': counterclockwise turn the right face
		// 0 <- 3
		// 3 <- 5
		// 5 <- 1
		// 1 <- 0
		int c020 = cState[0][2][0];
		int c021 = cState[0][2][1];
		int c022 = cState[0][2][2];

		cState[0][2][0] = cState[3][0][0];
		cState[0][2][1] = cState[3][1][0];
		cState[0][2][2] = cState[3][2][0];

		cState[3][0][0] = cState[5][0][2];
		cState[3][1][0] = cState[5][0][1];
		cState[3][2][0] = cState[5][0][0];

		cState[5][0][2] = cState[1][2][2];
		cState[5][0][1] = cState[1][1][2];
		cState[5][0][0] = cState[1][0][2];

		cState[1][2][2] = c020;
		cState[1][1][2] = c021;
		cState[1][0][2] = c022;

		CounterClockwise(2);
	}

	private void Uturn() {
		// U: upper face
		// 1 <- 2
		// 2 <- 3
		// 3 <- 4
		// 4 <- 1

		int c100 = cState[1][0][0];
		int c101 = cState[1][0][1];
		int c102 = cState[1][0][2];

		cState[1][0][0] = cState[2][0][0];
		cState[1][0][1] = cState[2][0][1];
		cState[1][0][2] = cState[2][0][2];

		cState[2][0][0] = cState[3][0][0];
		cState[2][0][1] = cState[3][0][1];
		cState[2][0][2] = cState[3][0][2];

		cState[3][0][0] = cState[4][0][0];
		cState[3][0][1] = cState[4][0][1];
		cState[3][0][2] = cState[4][0][2];

		cState[4][0][0] = c100;
		cState[4][0][1] = c101;
		cState[4][0][2] = c102;

		Clockwise(0);
	}

	private void Upturn() {
		// 1 <- 4
		// 4 <- 3
		// 3 <- 2
		// 2 <- 1

		int c100 = cState[1][0][0];
		int c101 = cState[1][0][1];
		int c102 = cState[1][0][2];

		cState[1][0][0] = cState[4][0][0];
		cState[1][0][1] = cState[4][0][1];
		cState[1][0][2] = cState[4][0][2];

		cState[4][0][0] = cState[3][0][0];
		cState[4][0][1] = cState[3][0][1];
		cState[4][0][2] = cState[3][0][2];

		cState[3][0][0] = cState[2][0][0];
		cState[3][0][1] = cState[2][0][1];
		cState[3][0][2] = cState[2][0][2];

		cState[2][0][0] = c100;
		cState[2][0][1] = c101;
		cState[2][0][2] = c102;

		CounterClockwise(0);
	}

	private void Bturn() {
		// 0 <- 2
		// 2 <- 5
		// 5 <- 4
		// 4 <- 0

		int c002 = cState[0][0][2];
		int c012 = cState[0][1][2];
		int c022 = cState[0][2][2];

		cState[0][0][2] = cState[2][0][2];
		cState[0][1][2] = cState[2][1][2];
		cState[0][2][2] = cState[2][2][2];

		cState[2][0][2] = cState[5][0][2];
		cState[2][1][2] = cState[5][1][2];
		cState[2][2][2] = cState[5][2][2];

		cState[5][0][2] = cState[4][2][0];
		cState[5][1][2] = cState[4][1][0];
		cState[5][2][2] = cState[4][0][0];

		cState[4][2][0] = c002;
		cState[4][1][0] = c012;
		cState[4][0][0] = c022;

		Clockwise(3);
	}

	private void Bpturn() {
		// 4 <- 5
		// 5 <- 2
		// 2 <- 0
		// 0 <- 4

		int c400 = cState[4][0][0];
		int c410 = cState[4][1][0];
		int c420 = cState[4][2][0];

		cState[4][2][0] = cState[5][0][2];
		cState[4][1][0] = cState[5][1][2];
		cState[4][0][0] = cState[5][2][2];

		cState[5][0][2] = cState[2][0][2];
		cState[5][1][2] = cState[2][1][2];
		cState[5][2][2] = cState[2][2][2];

		cState[2][0][2] = cState[0][0][2];
		cState[2][1][2] = cState[0][1][2];
		cState[2][2][2] = cState[0][2][2];

		cState[0][0][2] = c420;
		cState[0][1][2] = c410;
		cState[0][2][2] = c400;

		CounterClockwise(3);
	}

	private void Lturn() {
		// 0 <- 3
		// 3 <- 5
		// 5 <- 1
		// 1 <- 0
		int c000 = cState[0][0][0];
		int c001 = cState[0][0][1];
		int c002 = cState[0][0][2];

		cState[0][0][0] = cState[3][0][2];
		cState[0][0][1] = cState[3][1][2];
		cState[0][0][2] = cState[3][2][2];

		cState[3][0][2] = cState[5][2][2];
		cState[3][1][2] = cState[5][2][1];
		cState[3][2][2] = cState[5][2][0];

		cState[5][2][2] = cState[1][2][0];
		cState[5][2][1] = cState[1][1][0];
		cState[5][2][0] = cState[1][0][0];

		cState[1][2][0] = c000;
		cState[1][1][0] = c001;
		cState[1][0][0] = c002;

		Clockwise(4);
	}

	private void Lpturn() {
		// 0 <- 1
		// 1 <- 5
		// 5 <- 3
		// 3 <- 0
		int c000 = cState[0][0][0];
		int c001 = cState[0][0][1];
		int c002 = cState[0][0][2];

		cState[0][0][0] = cState[1][2][0];
		cState[0][0][1] = cState[1][1][0];
		cState[0][0][2] = cState[1][0][0];

		cState[1][2][0] = cState[5][2][2];
		cState[1][1][0] = cState[5][2][1];
		cState[1][0][0] = cState[5][2][0];

		cState[5][2][2] = cState[3][0][2];
		cState[5][2][1] = cState[3][1][2];
		cState[5][2][0] = cState[3][2][2];

		cState[3][0][2] = c000;
		cState[3][1][2] = c001;
		cState[3][2][2] = c002;

		CounterClockwise(4);
	}

	private void Dturn() {
		// 1 <- 4
		// 4 <- 3
		// 3 <- 2
		// 2 <- 1

		int c120 = cState[1][2][0];
		int c121 = cState[1][2][1];
		int c122 = cState[1][2][2];

		cState[1][2][0] = cState[4][2][0];
		cState[1][2][1] = cState[4][2][1];
		cState[1][2][2] = cState[4][2][2];

		cState[4][2][0] = cState[3][2][0];
		cState[4][2][1] = cState[3][2][1];
		cState[4][2][2] = cState[3][2][2];

		cState[3][2][0] = cState[2][2][0];
		cState[3][2][1] = cState[2][2][1];
		cState[3][2][2] = cState[2][2][2];

		cState[2][2][0] = c120;
		cState[2][2][1] = c121;
		cState[2][2][2] = c122;

		Clockwise(5);
	}

	private void Dpturn() {
		// 1 <- 2
		// 2 <- 3
		// 3 <- 4
		// 4 <- 1

		int c120 = cState[1][2][0];
		int c121 = cState[1][2][1];
		int c122 = cState[1][2][2];

		cState[1][2][0] = cState[2][2][0];
		cState[1][2][1] = cState[2][2][1];
		cState[1][2][2] = cState[2][2][2];

		cState[2][2][0] = cState[3][2][0];
		cState[2][2][1] = cState[3][2][1];
		cState[2][2][2] = cState[3][2][2];

		cState[3][2][0] = cState[4][2][0];
		cState[3][2][1] = cState[4][2][1];
		cState[3][2][2] = cState[4][2][2];

		cState[4][2][0] = c120;
		cState[4][2][1] = c121;
		cState[4][2][2] = c122;

		CounterClockwise(5);
	}

	private void Xrotate() {
		// 0 <- 1
		// 1 <- 5
		// 5 <- 3
		// 3 <- 0
		int c000 = cState[0][0][0];
		int c001 = cState[0][0][1];
		int c002 = cState[0][0][2];
		int c010 = cState[0][1][0];
		int c011 = cState[0][1][1];
		int c012 = cState[0][1][2];
		int c020 = cState[0][2][0];
		int c021 = cState[0][2][1];
		int c022 = cState[0][2][2];

		cState[0][0][0] = cState[1][2][0];
		cState[0][0][1] = cState[1][1][0];
		cState[0][0][2] = cState[1][0][0];
		cState[0][1][0] = cState[1][2][1];
		cState[0][1][1] = cState[1][1][1];
		cState[0][1][2] = cState[1][0][1];
		cState[0][2][0] = cState[1][2][2];
		cState[0][2][1] = cState[1][1][2];
		cState[0][2][2] = cState[1][0][2];

		cState[1][0][0] = cState[5][2][0];
		cState[1][1][0] = cState[5][2][1];
		cState[1][2][0] = cState[5][2][2];
		cState[1][0][1] = cState[5][1][0];
		cState[1][1][1] = cState[5][1][1];
		cState[1][2][1] = cState[5][1][2];
		cState[1][0][2] = cState[5][0][0];
		cState[1][1][2] = cState[5][0][1];
		cState[1][2][2] = cState[5][0][2];

		cState[5][2][0] = cState[3][2][2];
		cState[5][2][1] = cState[3][1][2];
		cState[5][2][2] = cState[3][0][2];
		cState[5][1][0] = cState[3][2][1];
		cState[5][1][1] = cState[3][1][1];
		cState[5][1][2] = cState[3][0][1];
		cState[5][0][0] = cState[3][2][0];
		cState[5][0][1] = cState[3][1][0];
		cState[5][0][2] = cState[3][0][0];

		cState[3][2][2] = c002;
		cState[3][1][2] = c001;
		cState[3][0][2] = c000;
		cState[3][2][1] = c012;
		cState[3][1][1] = c011;
		cState[3][0][1] = c010;
		cState[3][2][0] = c022;
		cState[3][1][0] = c021;
		cState[3][0][0] = c020;

		Clockwise(2);
		CounterClockwise(4);
	}

	private void Xprotate() {
		// 0 <- 3
		// 3 <- 5
		// 5 <- 1
		// 1 <- 0
		int c000 = cState[0][0][0];
		int c001 = cState[0][0][1];
		int c002 = cState[0][0][2];
		int c010 = cState[0][1][0];
		int c011 = cState[0][1][1];
		int c012 = cState[0][1][2];
		int c020 = cState[0][2][0];
		int c021 = cState[0][2][1];
		int c022 = cState[0][2][2];

		cState[0][0][0] = cState[3][0][2];
		cState[0][0][1] = cState[3][1][2];
		cState[0][0][2] = cState[3][2][2];
		cState[0][1][0] = cState[3][0][1];
		cState[0][1][1] = cState[3][1][1];
		cState[0][1][2] = cState[3][2][1];
		cState[0][2][0] = cState[3][0][0];
		cState[0][2][1] = cState[3][1][0];
		cState[0][2][2] = cState[3][2][0];

		cState[3][0][2] = cState[5][2][2];
		cState[3][1][2] = cState[5][2][1];
		cState[3][2][2] = cState[5][2][0];
		cState[3][0][1] = cState[5][1][2];
		cState[3][1][1] = cState[5][1][1];
		cState[3][2][1] = cState[5][1][0];
		cState[3][0][0] = cState[5][0][2];
		cState[3][1][0] = cState[5][0][1];
		cState[3][2][0] = cState[5][0][0];

		cState[5][2][2] = cState[1][2][0];
		cState[5][2][1] = cState[1][1][0];
		cState[5][2][0] = cState[1][0][0];
		cState[5][1][2] = cState[1][2][1];
		cState[5][1][1] = cState[1][1][1];
		cState[5][1][0] = cState[1][0][1];
		cState[5][0][2] = cState[1][2][2];
		cState[5][0][1] = cState[1][1][2];
		cState[5][0][0] = cState[1][0][2];

		cState[1][2][0] = c000;
		cState[1][1][0] = c001;
		cState[1][0][0] = c002;
		cState[1][2][1] = c010;
		cState[1][1][1] = c011;
		cState[1][0][1] = c012;
		cState[1][2][2] = c020;
		cState[1][1][2] = c021;
		cState[1][0][2] = c022;

		CounterClockwise(2);
		Clockwise(4);
	}

	private void Yrotate() {
		// 1 <- 2
		// 2 <- 3
		// 3 <- 4
		// 4 <- 1
		int c100 = cState[1][0][0];
		int c101 = cState[1][0][1];
		int c102 = cState[1][0][2];
		int c110 = cState[1][1][0];
		int c111 = cState[1][1][1];
		int c112 = cState[1][1][2];
		int c120 = cState[1][2][0];
		int c121 = cState[1][2][1];
		int c122 = cState[1][2][2];

		cState[1][0][0] = cState[2][0][0];
		cState[1][0][1] = cState[2][0][1];
		cState[1][0][2] = cState[2][0][2];
		cState[1][1][0] = cState[2][1][0];
		cState[1][1][1] = cState[2][1][1];
		cState[1][1][2] = cState[2][1][2];
		cState[1][2][0] = cState[2][2][0];
		cState[1][2][1] = cState[2][2][1];
		cState[1][2][2] = cState[2][2][2];

		cState[2][0][0] = cState[3][0][0];
		cState[2][0][1] = cState[3][0][1];
		cState[2][0][2] = cState[3][0][2];
		cState[2][1][0] = cState[3][1][0];
		cState[2][1][1] = cState[3][1][1];
		cState[2][1][2] = cState[3][1][2];
		cState[2][2][0] = cState[3][2][0];
		cState[2][2][1] = cState[3][2][1];
		cState[2][2][2] = cState[3][2][2];

		cState[3][0][0] = cState[4][0][0];
		cState[3][0][1] = cState[4][0][1];
		cState[3][0][2] = cState[4][0][2];
		cState[3][1][0] = cState[4][1][0];
		cState[3][1][1] = cState[4][1][1];
		cState[3][1][2] = cState[4][1][2];
		cState[3][2][0] = cState[4][2][0];
		cState[3][2][1] = cState[4][2][1];
		cState[3][2][2] = cState[4][2][2];

		cState[4][0][0] = c100;
		cState[4][0][1] = c101;
		cState[4][0][2] = c102;
		cState[4][1][0] = c110;
		cState[4][1][1] = c111;
		cState[4][1][2] = c112;
		cState[4][2][0] = c120;
		cState[4][2][1] = c121;
		cState[4][2][2] = c122;

		Clockwise(0);
		CounterClockwise(5);
	}

	private void Yprotate() {
		// 1 <- 4
		// 4 <- 3
		// 3 <- 2
		// 2 <- 1
		int c100 = cState[1][0][0];
		int c101 = cState[1][0][1];
		int c102 = cState[1][0][2];
		int c110 = cState[1][1][0];
		int c111 = cState[1][1][1];
		int c112 = cState[1][1][2];
		int c120 = cState[1][2][0];
		int c121 = cState[1][2][1];
		int c122 = cState[1][2][2];

		cState[1][0][0] = cState[4][0][0];
		cState[1][0][1] = cState[4][0][1];
		cState[1][0][2] = cState[4][0][2];
		cState[1][1][0] = cState[4][1][0];
		cState[1][1][1] = cState[4][1][1];
		cState[1][1][2] = cState[4][1][2];
		cState[1][2][0] = cState[4][2][0];
		cState[1][2][1] = cState[4][2][1];
		cState[1][2][2] = cState[4][2][2];

		cState[4][0][0] = cState[3][0][0];
		cState[4][0][1] = cState[3][0][1];
		cState[4][0][2] = cState[3][0][2];
		cState[4][1][0] = cState[3][1][0];
		cState[4][1][1] = cState[3][1][1];
		cState[4][1][2] = cState[3][1][2];
		cState[4][2][0] = cState[3][2][0];
		cState[4][2][1] = cState[3][2][1];
		cState[4][2][2] = cState[3][2][2];

		cState[3][0][0] = cState[2][0][0];
		cState[3][0][1] = cState[2][0][1];
		cState[3][0][2] = cState[2][0][2];
		cState[3][1][0] = cState[2][1][0];
		cState[3][1][1] = cState[2][1][1];
		cState[3][1][2] = cState[2][1][2];
		cState[3][2][0] = cState[2][2][0];
		cState[3][2][1] = cState[2][2][1];
		cState[3][2][2] = cState[2][2][2];

		cState[2][0][0] = c100;
		cState[2][0][1] = c101;
		cState[2][0][2] = c102;
		cState[2][1][0] = c110;
		cState[2][1][1] = c111;
		cState[2][1][2] = c112;
		cState[2][2][0] = c120;
		cState[2][2][1] = c121;
		cState[2][2][2] = c122;

		CounterClockwise(0);
		Clockwise(5);
	}

	private void Zrotate() {
		// 0 <- 4
		// 4 <- 5
		// 5 <- 2
		// 2 <- 0
		int c000 = cState[0][0][0];
		int c001 = cState[0][0][1];
		int c002 = cState[0][0][2];
		int c010 = cState[0][1][0];
		int c011 = cState[0][1][1];
		int c012 = cState[0][1][2];
		int c020 = cState[0][2][0];
		int c021 = cState[0][2][1];
		int c022 = cState[0][2][2];

		cState[0][0][0] = cState[4][2][2];
		cState[0][0][1] = cState[4][2][1];
		cState[0][0][2] = cState[4][2][0];
		cState[0][1][0] = cState[4][1][2];
		cState[0][1][1] = cState[4][1][1];
		cState[0][1][2] = cState[4][1][0];
		cState[0][2][0] = cState[4][0][2];
		cState[0][2][1] = cState[4][0][1];
		cState[0][2][2] = cState[4][0][0];

		cState[4][0][2] = cState[5][2][0];
		cState[4][1][2] = cState[5][1][0];
		cState[4][2][2] = cState[5][0][0];
		cState[4][0][1] = cState[5][2][1];
		cState[4][1][1] = cState[5][1][1];
		cState[4][2][1] = cState[5][0][1];
		cState[4][0][0] = cState[5][2][2];
		cState[4][1][0] = cState[5][1][2];
		cState[4][2][0] = cState[5][0][2];

		cState[5][0][0] = cState[2][0][0];
		cState[5][0][1] = cState[2][0][1];
		cState[5][0][2] = cState[2][0][2];
		cState[5][1][0] = cState[2][1][0];
		cState[5][1][1] = cState[2][1][1];
		cState[5][1][2] = cState[2][1][2];
		cState[5][2][0] = cState[2][2][0];
		cState[5][2][1] = cState[2][2][1];
		cState[5][2][2] = cState[2][2][2];

		cState[2][0][0] = c000;
		cState[2][0][1] = c001;
		cState[2][0][2] = c002;
		cState[2][1][0] = c010;
		cState[2][1][1] = c011;
		cState[2][1][2] = c012;
		cState[2][2][0] = c020;
		cState[2][2][1] = c021;
		cState[2][2][2] = c022;

		Clockwise(1);
		CounterClockwise(3);
	}

	private void Zprotate() {
		// 0 <- 2
		// 2 <- 5
		// 5 <- 4
		// 4 <- 0

		int c000 = cState[0][0][0];
		int c001 = cState[0][0][1];
		int c002 = cState[0][0][2];
		int c010 = cState[0][1][0];
		int c011 = cState[0][1][1];
		int c012 = cState[0][1][2];
		int c020 = cState[0][2][0];
		int c021 = cState[0][2][1];
		int c022 = cState[0][2][2];

		cState[0][0][0] = cState[2][0][0];
		cState[0][0][1] = cState[2][0][1];
		cState[0][0][2] = cState[2][0][2];
		cState[0][1][0] = cState[2][1][0];
		cState[0][1][1] = cState[2][1][1];
		cState[0][1][2] = cState[2][1][2];
		cState[0][2][0] = cState[2][2][0];
		cState[0][2][1] = cState[2][2][1];
		cState[0][2][2] = cState[2][2][2];

		cState[2][0][0] = cState[5][0][0];
		cState[2][0][1] = cState[5][0][1];
		cState[2][0][2] = cState[5][0][2];
		cState[2][1][0] = cState[5][1][0];
		cState[2][1][1] = cState[5][1][1];
		cState[2][1][2] = cState[5][1][2];
		cState[2][2][0] = cState[5][2][0];
		cState[2][2][1] = cState[5][2][1];
		cState[2][2][2] = cState[5][2][2];

		cState[5][0][0] = cState[4][2][2];
		cState[5][0][1] = cState[4][2][1];
		cState[5][0][2] = cState[4][2][0];
		cState[5][1][0] = cState[4][1][2];
		cState[5][1][1] = cState[4][1][1];
		cState[5][1][2] = cState[4][1][0];
		cState[5][2][0] = cState[4][0][2];
		cState[5][2][1] = cState[4][0][1];
		cState[5][2][2] = cState[4][0][0];

		cState[4][0][0] = c022;
		cState[4][0][1] = c021;
		cState[4][0][2] = c020;
		cState[4][1][0] = c012;
		cState[4][1][1] = c011;
		cState[4][1][2] = c010;
		cState[4][2][0] = c002;
		cState[4][2][1] = c001;
		cState[4][2][2] = c000;

		CounterClockwise(1);
		Clockwise(3);
	}

	private Boolean IsCubeState(String t) // NOTE: does not check if state is
	// valid!
	{
		if (t.length() != 54) {
			return false;
		}
		for (int i = 0; i < 54; i++) {
			if (!COLORMAP.containsKey(Character.toString(t.charAt(i)))) {
				return false;
			}
		}
		return true;
	}

	/*
	 * private void InitColorMap() { COLORMAP.put("Y", new Integer(0));
	 * COLORMAP.put("R", new Integer(1)); COLORMAP.put("G", new Integer(2));
	 * COLORMAP.put("O", new Integer(3)); COLORMAP.put("B", new Integer(4));
	 * COLORMAP.put("W", new Integer(5)); }
	 */

	public String print() {
		char printState[] = new char[54];
		int i = 0;
		// rotate back so that the centers are always Y R O G B W
		for (int r = rotate.size() - 1; r >= 0; r--) {
			String cmd = rotate.get(r);
			if (cmd == "X") {
				Xprotate();
			}
			if (cmd == "X'") {
				Xrotate();
			}
			if (cmd == "Y") {
				Yprotate();
			}
			if (cmd == "Y'") {
				Yrotate();
			}
			if (cmd == "Z") {
				Zprotate();
			}
			if (cmd == "Z'") {
				Zrotate();
			}
		}
		for (int face = 0; face < NUMFACE; face++) {
			for (int row = 0; row < CUBESIZE; row++) {
				for (int col = 0; col < CUBESIZE; col++) {
					printState[i++] = FACECOLOR[cState[face][row][col]];
				}
			}
			// cout + " ";
		}
		System.out.println();
		// rotate again
		for (int r = 0; r < rotate.size(); r++) {
			String cmd = rotate.get(r);
			if (cmd == "X") {
				Xrotate();
			}
			if (cmd == "X'") {
				Xprotate();
			}
			if (cmd == "Y") {
				Yrotate();
			}
			if (cmd == "Y'") {
				Yprotate();
			}
			if (cmd == "Z") {
				Zrotate();
			}
			if (cmd == "Z'") {
				Zprotate();
			}
		}

		return new String(printState);
		// find the order of the centers
		/*
		 * int order[] = new int[NUMFACE]; for (int f1 = 0; f1 < NUMFACE; f1 ++)
		 * { for (int f2 = 0; f2 < NUMFACE; f2 ++) { if (cState[f2][1][1] == f1)
		 * { order[f1] = f2; } } } for (int face = 0; face < NUMFACE; face ++) {
		 * for (int row = 0; row < CUBESIZE; row ++) { for (int col = 0; col <
		 * CUBESIZE; col ++) {
		 * System.out.print(FACECOLOR[cState[order[face]][row][col]]); } }
		 * System.out.print(" "); } System.out.println();
		 */
	}
}